#include "BleManager.h"
#include <mutex>

static std::mutex mtx; // 全局互斥锁

BleServerConnector BleManager::s_bleConnectors[BLE_COUNT_MAX];

BleManager::BleManager() {
}

void BleManager::backend(void *pvParameters) {

    for (;;) {
        for (int i = 0; i < BLE_COUNT_MAX; i++) {
            if (s_bleConnectors[i]._fixed) {
                s_bleConnectors[i].connectToServer();
            }
        }
        vTaskDelay(100);
    }
}

void BleManager::startScan() {
    if (isScan) {
        return;
    }
    isScan = true;
    // 开启后台任务
    xTaskCreatePinnedToCore(
        scan,               // 任务函数
        "BleManager::scan", // 任务名称
        8 * 1024,           // 堆栈大小（字节）
        this,               // 参数
        1,                  // 优先级（与默认 loop() 相同）
        NULL,               // 任务句柄（可选）
        1                   // 核心编号（1）
    );
}

void BleManager::scan(void *pvParameters) {
    BleManager *bleManager = (BleManager *)pvParameters;
    // 获取一个扫描器，设置回调函数
    BLEScan *pBLEScan = BLEDevice::getScan();
    // pBLEScan->setScanCallbacks(this, false);
    pBLEScan->setInterval(1349);   // 扫描间隔(ms)
    pBLEScan->setWindow(449);      // 扫描窗口
    pBLEScan->setActiveScan(true); // 主动扫描
    pBLEScan->setMaxResults(20);

    // 扫描3秒
    NimBLEScanResults results = pBLEScan->getResults(3000, false); // false : 在扫描结束后不自动删除结果

    mtx.lock();

    for (int i = 0; i < BLE_COUNT_MAX; i++) {
        if (!s_bleConnectors[i]._fixed) {
            s_bleConnectors[i].destory();
        }
    }

    for (int i = 0; i < results.getCount(); i++) {
        bleManager->onResult(results.getDevice(i));
    }
    mtx.unlock();

    // 删除扫描结果
    pBLEScan->clearResults();

    bleManager->isScan = false;
    vTaskDelete(NULL); // 删除任务
}

void BleManager::init(std::string deviceName) {
    NimBLEDevice::init(deviceName);

    // 开启后台任务
    xTaskCreatePinnedToCore(
        backend,               // 任务函数
        "BleManager::backend", // 任务名称
        8 * 1024,              // 堆栈大小（字节）
        this,                  // 参数
        1,                     // 优先级（与默认 loop() 相同）
        NULL,                  // 任务句柄（可选）
        1                      // 核心编号（1）
    );
}

BleServerConnector *BleManager::getBleServerConnector(String address) {
    for (int i = 0; i < BLE_COUNT_MAX; i++) {
        if (!s_bleConnectors[i].isEmpty() && strcmp(s_bleConnectors[i]._address, address.c_str()) == 0) {
            return &s_bleConnectors[i];
        }
    }
    return nullptr;
}

void BleManager::pairDevice(BleServerConnector *pConnector) {

    pConnector->_status = 0;
    pConnector->_fixed = true;
}

void BleManager::removePairedDevice(BleServerConnector *pConnector) {

    pConnector->destory();
    pConnector->_fixed = false;
}

// 回调函数： 处理广播信息
void BleManager::onResult(const NimBLEAdvertisedDevice *advertisedDevice) {

    const char *address = advertisedDevice->getAddress().toString().c_str();

    // 寻找空位
    int idx = -1;
    for (int i = 0; i < BLE_COUNT_MAX; i++) {
        if (s_bleConnectors[i]._isEmpty) {
            idx = i;
            break;
        }
    }

    // 没找到
    if (idx == -1) {
        return;
    }

    BleServerConnector &connector = s_bleConnectors[idx];

    // 看看他是否是键盘或鼠标
    // 外观
    uint16_t appearance = advertisedDevice->getAppearance();
    if (appearance == 0x03C1) {
        // 键盘(0x03C1)
        connector._type = 1;
    } else if (appearance == 0x03C2) {
        // 鼠标(0x03C2)
        connector._type = 2;
    } else {
        return;
    }

    // 设备名称
    strcpy(connector._name, advertisedDevice->getName().c_str());
    // 设备地址
    strcpy(connector._address, address);
    connector._addressType = advertisedDevice->getAddressType();

    connector._isEmpty = false;
}

void BleManager::onRecvData(BLERemoteCharacteristic *pReadReportCharacteristic, uint8_t *dataBuf, int nLen, bool isNotify) {
    for (int i = 0; i < BLE_COUNT_MAX; i++) {
        BleServerConnector *pCconnect = &s_bleConnectors[i];
        if (!pCconnect->isEmpty() && pCconnect->_pReadReportCharacteristic == pReadReportCharacteristic) {
            pCconnect->recvData(dataBuf, nLen, isNotify);
            break;
        }
    }
}

void BleManager::createConnection(char address[18], uint8_t addressType, int deviceType, char *deviceName) {

    // 寻找空位
    int idx = -1;
    for (int i = 0; i < BLE_COUNT_MAX; i++) {
        if (s_bleConnectors[i]._isEmpty) {
            idx = i;
            break;
        }
    }

    // 没找到
    if (idx == -1) {
        return;
    }

    BleServerConnector &connector = s_bleConnectors[idx];
    connector._type = deviceType;

    // 设备名称
    strcpy(connector._name, deviceName);
    // 设备地址
    strcpy(connector._address, address);
    connector._addressType = addressType;

    connector._isEmpty = false;
}

BleManager _BleManager;